package com.nl.redis;

import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Tuple;

/**
 * RedisCluster操作类
 * @author zhxf
 *
 */
public class RedisCluster {

	private String resConf;
	/**
	 * 默认值
	 */
	String defaultValue = "-1";
	private String[] cfgStr;
	private JedisCluster jedisCluster;

	public RedisCluster(String resConf, String defaultValue) throws IOException{
		this.resConf = resConf;
		this.defaultValue = defaultValue;
		cfgStr = resConf.split("%_%");
		initialJedisCluster();
	}
	
	public RedisCluster(String resConf) throws IOException{
		this.resConf = resConf;
		cfgStr = resConf.split("%_%");
		initialJedisCluster();
	}
	
	public RedisCluster(String resConf, String defaultValue, JedisPoolConfig config) throws IOException{
		this.resConf = resConf;
		this.defaultValue = defaultValue;
		cfgStr = resConf.split("%_%");
		initialJedisCluster(config);
	}
	
	public RedisCluster(String resConf, JedisPoolConfig config) throws IOException{
		this.resConf = resConf;
		cfgStr = resConf.split("%_%");
		initialJedisCluster(config);
	}
	
	/**
	 * 获得rediscluster配置信息
	 * @return
	 */
	public String getRedisInfo(){
		return resConf;
	}
	
	/**
	 * 设置rediscluster配置信息
	 * @param cfg
	 * @param defaultValue
	 */
	public void setRedisInfo(String cfg, String defaultValue) throws IOException{
		this.resConf = cfg;
		this.defaultValue = defaultValue;
		cfgStr = resConf.split("%_%");
		initialJedisCluster();
	}
	
	/**
	 * 设置rediscluster配置信息
	 * @param cfg
	 */
	public void setRedisInfo(String cfg) throws IOException{
		this.resConf = cfg;
		cfgStr = resConf.split("%_%");
		initialJedisCluster();
	}
	

	/**
	 * 设置rediscluster配置信息
	 * @param cfg
	 * @param defaultValue
	 */
	public void setRedisInfo(String cfg, String defaultValue, JedisPoolConfig config) throws IOException{
		this.resConf = cfg;
		this.defaultValue = defaultValue;
		cfgStr = resConf.split("%_%");
		initialJedisCluster(config);
	}
	
	/**
	 * 设置rediscluster配置信息
	 * @param cfg
	 */
	public void setRedisInfo(String cfg, JedisPoolConfig config) throws IOException{
		this.resConf = cfg;
		cfgStr = resConf.split("%_%");
		initialJedisCluster(config);
	}
	
	/**
	 * 插入数据
	 * @param key
	 * @param value
	 */
	public void set(String key, String value){
		jedisCluster.set(key, value);
	}
	
	/**
	 * 插入数据(SortedSet)
	 * @param key
	 * @param value
	 * @param order
	 */
	public void zadd(String key, String value, String order){
		jedisCluster.zadd(key, Double.parseDouble(order), value);
	}
	
	/**
	 * 插入数据(SortedSet)
	 * @param key
	 * @param value
	 * @param order
	 */
	public void zadd(String key, String value, double order){
		jedisCluster.zadd(key, order, value);
	}
	
	/**
	 * 移除(SortedSet)
	 * @param key
	 * @param member
	 */
	public void zrem(String key, String member){
		jedisCluster.zrem(key, member);
	}
	
	/**
	 * 设置key有效时间
	 * @param key
	 * @param seconds
	 */
	public void expire(String key, int seconds){
		jedisCluster.expire(key, seconds);
	}
	
	public void setex(String key, String value, int seconds){
		jedisCluster.setex(key, seconds, value);
	}

	/**
	 * 读取数据
	 * @param key
	 * @return
	 */
	public String get(String key) {
		return jedisCluster.get(key);
	}
	
	public Map<String, String> hgetAll(String key) {
		return jedisCluster.hgetAll(key);
	}
	
	public void hset(String key, String field, String value) {
		jedisCluster.hset(key, field, value);
	}
	
	public void hmset(String key, Map<String, String> hash) {
		jedisCluster.hmset(key, hash);
	}
	
	public String  hget(String key, String field) {
		return jedisCluster.hget(key, field);
	}
	
	public Long del(String key) {
		Long i =jedisCluster.del(key);
		return i;
	}
	
	/**
	 * 是否存在key
	 * @param key
	 * @return
	 */
	public boolean existKey(String key){
		return jedisCluster.exists(key);
	}
	
	/**
	 * 增量操作(+)
	 */
	public void incrBy(String key, long value){
		jedisCluster.incrBy(key, value);
	}
	
	/**
	 * hash增量操作(Hash)
	 * @param key
	 * @param vaule
	 */
	public void hincrBy(String key, String field, long value){
		jedisCluster.hincrBy(key, field, value);
	}
	
	/**
	 * 是否包含指定元素(Set)
	 * @param key
	 * @param value
	 * @return
	 */
	public boolean isMember(String key, String value){
		return jedisCluster.sismember(key, value);
	}
	
	/**
	 * 从大到小返回区间值的第一个(SortedSet)
	 * @param key
	 * @param max
	 * @return
	 */
	public String zrevrangeByScore(String key, String max){
		Set<String> result = jedisCluster.zrevrangeByScore(key, max, "-inf", 0, 1);
		if(result.size() > 0){
			return result.iterator().next();
		}
		return "";
	}
	
	public Set<String> sZrevrangeByScore(String key, String max){
		return jedisCluster.zrevrangeByScore(key, max, "-inf");
	}
	
	/**
	 * 从大到小返回区间值的第一个(SortedSet)
	 * @param key
	 * @param max
	 * @return
	 */
	public Tuple zrevrangeByScoreWithScores(String key, String max){
		Set<Tuple> result = jedisCluster.zrevrangeByScoreWithScores(key, max, "-inf", 0, 1);
		if(result.size() > 0){
			return result.iterator().next();
		}
		return null;
	}
	
	/**
	 * 从大到小返回区间值的第一个(SortedSet)
	 * @param key
	 * @param max
	 * @return
	 */
	public String zrevrangeByScore(String key, double max, double min){
		Set<String> result = jedisCluster.zrevrangeByScore(key, max, min, 0, 1);
		if(result.size() > 0){
			return result.iterator().next();
		}
		return "";
	}
	
	/**
	 * 从大到小返回区间值的第一个(SortedSet)
	 * @param key
	 * @param max
	 * @return
	 */
	public Tuple zrevrangeByScoreWithScores(String key, String max, String min){
		Set<Tuple> result = jedisCluster.zrevrangeByScoreWithScores(key, max, min, 0 , 1);
		if(result.size() > 0){
			return result.iterator().next();
		}
		return null;
	}
	
	/**
	 * 从大到小返回区间值的第一个(SortedSet)
	 * @param key
	 * @param max
	 * @return
	 */
	public Tuple zrevrangeByScoreWithScores(String key, double max, double min){
		Set<Tuple> result = jedisCluster.zrevrangeByScoreWithScores(key, max, min, 0 , 1);
		if(result.size() > 0){
			return result.iterator().next();
		}
		return null;
	}
	
	/**
	 * 从大到小返回区间值的第一个(SortedSet)
	 * @param key
	 * @param max
	 * @return
	 */
	public String zrange(String key){
		Set<String> result = jedisCluster.zrevrange(key, 0, 0);
		if(result.size() > 0){
			return result.iterator().next();
		}
		return "";
	}
	
	/**
	 * 返回区间内的所有值(SortedSet)
	 * @param key
	 * @param start
	 * @param end
	 * @return
	 */
	public Set<Tuple> zrange(String key, long start, long end){
		return jedisCluster.zrangeWithScores(key, start, end);
	}
	
	/**
	 * 返回所有区间的值(SortedSet)
	 * @param key
	 * @param start
	 * @param end
	 * @return
	 */
	public Set<String> zrangeWithoutScores(String key, long start, long end){
		return jedisCluster.zrange(key, start, end);
	}
	
	/**
	 * 从小到大，返回区间内的第一个值
	 * @param key
	 * @param min
	 * @return
	 */
	public String zrangeByScore(String key, String min){
		Set<String> result = jedisCluster.zrangeByScore(key, min, "+inf", 0, 1);
		if(result.size() > 0){
			return result.iterator().next();
		}
		return "";
	}
	
	/**
	 * 从小到大，返回区间内的第一个值
	 * @param key
	 * @param min
	 * @return
	 */
	public Tuple zrangeByScoreWithScores(String key, String min){
		Set<Tuple> result = jedisCluster.zrangeByScoreWithScores(key, min, "+inf", 0, 1);
		if(result.size() > 0){
			return result.iterator().next();
		}
		return null;
	}
	
	/**
	 * 删除指定区间的值(SortedSet)
	 * @param key
	 * @param min
	 * @param max
	 */
	public void zremrangeByScore(String key, double min, double max){ 
		jedisCluster.zremrangeByScore(key, min, max);
	}
	
	/**
	 * 删除指定区间的值(SortedSet)
	 * @param key
	 * @param min
	 * @param max
	 */
	public void zremrangeByScore(String key, String min, String max){
		jedisCluster.zremrangeByScore(key, min, max);
	}
	
	public List<String> hmget(String key, String... fields){
		return jedisCluster.hmget(key, fields);
	}
	
	/**
	 * 初始化RedisCluster
	 */
	private void initialJedisCluster() throws IOException{
		JedisPoolConfig config = new JedisPoolConfig();
	    config.setMaxTotal(5);
	    config.setMaxIdle(1);
	    config.setMinIdle(1);
	    config.setMaxWaitMillis(10 * 1000);
	    config.setTestOnBorrow(false);
	    
	    Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
	    String password = null;
	    for(String str : cfgStr){
	    	String[] cStr = str.split(":");
	    	jedisClusterNodes.add(new HostAndPort(cStr[0], Integer.parseInt(cStr[1])));
	    	if(cStr.length == 3){
	    		password = cStr[2];
	    	}
	    }
	    if(null != jedisCluster){
			jedisCluster.close();
	    }
	    if(null == password){
	    	jedisCluster = new JedisCluster(jedisClusterNodes, jedisClusterNodes.size() * 1000, jedisClusterNodes.size(), config);
	    } else {
	    	jedisCluster =  new JedisCluster(jedisClusterNodes, jedisClusterNodes.size() * 1000, jedisClusterNodes.size() * 1000, jedisClusterNodes.size(), password, config);
	    }
	}
	
	/**
	 * 初始化RedisCluster
	 */
	private void initialJedisCluster(JedisPoolConfig config) throws IOException{
	    Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
	    String password = null;
	    for(String str : cfgStr){
	    	String[] cStr = str.split(":");
	    	jedisClusterNodes.add(new HostAndPort(cStr[0], Integer.parseInt(cStr[1])));
	    	if(cStr.length == 3){
	    		password = cStr[2];
	    	}
	    }
	    if(null != jedisCluster){
			jedisCluster.close();
	    }
	    if(null == password){
	    	jedisCluster = new JedisCluster(jedisClusterNodes, jedisClusterNodes.size() * 1000, jedisClusterNodes.size(), config);
	    } else {
	    	jedisCluster =  new JedisCluster(jedisClusterNodes, jedisClusterNodes.size() * 1000, jedisClusterNodes.size() * 1000, jedisClusterNodes.size(), password, config);
	    }
	}
	
	public void close() throws IOException{
		if(null != jedisCluster){
			jedisCluster.close();
	    }
	}
	
}
